package com.ezops.dao.facade;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

import org.apache.poi.ss.usermodel.DataValidation;
import org.apache.poi.ss.usermodel.DataValidationConstraint;
import org.apache.poi.ss.usermodel.DataValidationHelper;
import org.apache.poi.ss.util.CellRangeAddressList;
import org.apache.poi.xssf.usermodel.XSSFDataValidationHelper;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.ezops.dao.ClientDAO;
import com.ezops.dao.ClientEzopsFieldMappingDAO;
import com.ezops.dao.ClientFieldDAO;
import com.ezops.dao.EzopsClientDAO;
import com.ezops.dao.EzopsFieldDAO;
import com.ezops.dao.generics.dao.hibernate.GenericDAO;
import com.ezops.models.Client;
import com.ezops.models.ClientEzopsFieldMappingModel;
import com.ezops.models.ClientFields;
import com.ezops.models.EzopsClient;
import com.ezops.models.EzopsFields;
import com.ezops.util.Report;
import com.ezops.util.Report.Row;

/***
 * Users DataTransfer Facade , handles all general Users object cache access
 * operations
 * 
 * @author HindsC
 * 
 */
@Service
public class ClientDataTransferFacade extends DataTransferFacadeImpl<Client>
		implements IClientDataTransferFacade {

	private static final String EZOPS_FIELD = "Ezops";
	private static final String CLIENT_FIELD = "Client";
	final static Logger logger = LoggerFactory
			.getLogger(ClientDataTransferFacade.class);

	@Autowired
	private ClientDAO dao;

	@Autowired
	private ClientFieldDAO clientFieldDAO;

	@Autowired
	private ClientEzopsFieldMappingDAO clientEzopsFieldMappingDAO;

	@Autowired
	private EzopsFieldDAO ezopsFieldDAO;

	@Autowired
	private EzopsClientDAO ezopsClientDAO;

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.ezops.dao.facade.IClientDataTransferFacade#getAllClientFields(java
	 * .lang.String, java.lang.String)
	 */
	@Override
	public List<ClientFields> getAllClientFields(String clientId, String assetId) {

		List<ClientFields> clientFieldsList = clientFieldDAO
				.getAllClientFields(Integer.parseInt(clientId),
						Integer.parseInt(assetId));
		Collections.sort(clientFieldsList);
		return clientFieldsList;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.ezops.dao.facade.IClientDataTransferFacade#getAllEzopsFields()
	 */
	@Override
	public List<EzopsFields> getAllEzopsFields() {
		List<EzopsFields> ezopsFieldsList = ezopsFieldDAO.findAll();
		Collections.sort(ezopsFieldsList);
		return ezopsFieldsList;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.ezops.dao.facade.IClientDataTransferFacade#getAllMapping(java.lang
	 * .String, java.lang.String)
	 */
	@Override
	public List<ClientEzopsFieldMappingModel> getAllMapping(String clientId,
			String assetId) {

		return clientEzopsFieldMappingDAO.getAllMapping(
				Integer.parseInt(clientId), Integer.parseInt(assetId));
	}

	/**
	 * Save client-ezops fields mappings
	 */
	@Override
	@Transactional(propagation=Propagation.REQUIRED)
	public boolean saveFieldMappings(
			List<ClientEzopsFieldMappingModel> fieldMappingJson) {
		clientEzopsFieldMappingDAO.save(fieldMappingJson
				.toArray(new ClientEzopsFieldMappingModel[fieldMappingJson
						.size()]));

		return true;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.ezops.dao.facade.IClientDataTransferFacade#convertTo(java.io.InputStream
	 * )
	 */
	@Override
	public List<ClientEzopsFieldMappingModel> convertTo(InputStream is)
			throws IOException {
		List<ClientEzopsFieldMappingModel> mappings = new ArrayList<>();

		Report report = new Report(is);
		Iterator<Row> iteretor = report.iterator();
		boolean isDataStartHere = false;
		while (iteretor.hasNext()) {
			Row row = iteretor.next();
			if (row.getValue(0).trim().equalsIgnoreCase("Client Field")) {
				isDataStartHere = true;
				continue;
			}

			if (isDataStartHere) {
				// Need id from field name.
				ClientEzopsFieldMappingModel mapping = new ClientEzopsFieldMappingModel();
				ClientFields clientField = new ClientFields();
				clientField.setId(lookUp(row.getValue(0), CLIENT_FIELD));
				clientField.setAssetId(1);
				clientField.setClientId(1);
				mapping.setClientField(clientField);
				mapping.setId(lookUp(row.getValue(0), CLIENT_FIELD));

				EzopsFields ezopsField = new EzopsFields();
				ezopsField.setId(lookUp(row.getValue(1), EZOPS_FIELD));
				mapping.setEzopsField(ezopsField);
				mapping.setEzopsFieldId(lookUp(row.getValue(1), EZOPS_FIELD));
				mappings.add(mapping);

			}

		}
		return mappings;
	}

	/**
	 * Return the field ID by looking up the field name,
	 * 
	 * @param value
	 * @param key
	 * @return
	 */
	private int lookUp(String value, String key) {
		if (EZOPS_FIELD.equals(key)) {
			for (EzopsFields fields : getAllEzopsFields()) {
				if (fields.getEzopsFieldName().trim()
						.equalsIgnoreCase(value.trim())) {
					// TODO - when the Domain entity change to {@code int
					// getId()} chnage this code as well.
					return Integer.parseInt(fields.getId());
				}
			}
		} else if (CLIENT_FIELD.equals(key)) {
			for (ClientFields clientField : getAllClientFields("1", "1")) {
				if (clientField.getFieldName().trim()
						.equalsIgnoreCase(value.trim())) {
					return clientField.getClientId();
				}
			}

		}
		return 0;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.ezops.dao.facade.IClientDataTransferFacade#getAllEzopsClients()
	 */
	@Override
	public List<EzopsClient> getAllEzopsClients() {
		return ezopsClientDAO.findAll();
	}

	public static void main(String[] args) throws IOException {

		DataValidation dataValidation = null;
		DataValidationConstraint constraint = null;
		DataValidationHelper validationHelper = null;

		XSSFWorkbook wb = new XSSFWorkbook();
		XSSFSheet sheet1 = (XSSFSheet) wb.createSheet("sheet1");

		validationHelper = new XSSFDataValidationHelper(sheet1);
		CellRangeAddressList addressList = new CellRangeAddressList(0, 5, 0, 0);
		constraint = validationHelper
				.createExplicitListConstraint(new String[] { "SELECT", "10",
						"20", "30" });
		dataValidation = validationHelper.createValidation(constraint,
				addressList);
		dataValidation.setSuppressDropDownArrow(true);
		sheet1.addValidationData(dataValidation);

		FileOutputStream fileOut = new FileOutputStream(
				"/Users/vgaurav/Documents/testDD.xlsx");
		wb.write(fileOut);
		fileOut.close();
	}

	@Override
	public GenericDAO<Client, Serializable> getDataAccessObject() {
		// TODO Auto-generated method stub
		return dao;
	}

}
